package com.example.logback;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.junit.jupiter.api.Test;


import java.io.File;
import java.io.FileFilter;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author: zouren
 * @date: 2023/7/15
 * @description:
 */
public class CreateExecel {
    public static final String g = " ";
    public static final String lt = "\n\t";
    public static final String times_reg = "(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\.\\d{3}.+LogAspect.*Api\\..*";
    public static final String Exception_reg = ".+Exception:.+";
    public static final String ERROR_reg = "(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\.\\d{3}.+ERROR.*";
    public static final Pattern api_pattern = Pattern.compile(times_reg);
    public static final Pattern exception_pattern = Pattern.compile(Exception_reg);
    public static final Pattern ERROR_pattern = Pattern.compile(ERROR_reg);
    public static final String readLogspath = "D:\\logs\\log-07-24";
    private static List<Log> getInputStream(String path) {
        List<File> files = FileUtil.loopFiles(path, new FileFilter(){

            /**
             * Tests whether or not the specified abstract pathname should be
             * included in a pathname list.
             *
             * @param pathname The abstract pathname to be tested
             * @return <code>true</code> if and only if <code>pathname</code>
             * should be included
             */
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().indexOf(".log")>=0;
            }
        });
        int len = files.size();
        List<Log> re = new ArrayList<>(300000);
        for (int i = 0; i < len; i++) {
            re.addAll(analysis(files.get(i)));
        }
        return re;
    }

    private static List<Log> analysis(File logFile) {
        System.out.println("roading " + logFile.getName());
        LinkedList<Log> re = new LinkedList<Log>();
        List<String> contents = FileUtil.readLines(logFile, CharsetUtil.CHARSET_UTF_8);
        int len = contents.size();
        String logName = logFile.getName();
        Log row = null;
        String content = null;
        int mIndex = 0;
        Map<String, Integer> thread = new HashMap<>();
        Map<String, Integer> ERROR = new HashMap<>();
        int freeMemory = 0;
        for (int i = 0; i < len; i++) {
            content = contents.get(i);
//            System.err.println("start==" + content);

            if (content.length() >= 500) {
                content = content.substring(0, 500);
            }
            mIndex = content.indexOf("freeMemory:");
            if(mIndex>0){
                freeMemory = Integer.parseInt(content.substring(mIndex+11));
            }
            boolean isAPi = api_pattern.matcher(content).find();
            boolean isException = exception_pattern.matcher(content).find();
            //只记标准的API
            if (isAPi || isException) {
                String[] s = content.split(g);
                if (isAPi && s[10].startsWith("param:")) {
                    //开始api
                    row = new Log();
                    row.setLogName(logName);
                    row.setStartData(s[0] + g + s[1]);
                    row.setPodName(s[5]);
                    row.setStartline(i + "");
                    row.setApiName(s[8]);
                    row.setThreadName(s[2]);
                    re.addLast(row);
                    thread.put(row.getThreadName(), re.size() - 1);
                } else if (isAPi) {
                    Integer _index = thread.get(s[2]);
                    if (_index != null) {
                        row = re.get(_index);
                    }
                    if (row != null && row.getApiName().equals(s[8]) && row.getPodName().equals(s[5])) {
                        row.setEndData(s[0] + g + s[1]);
                        row.setEndline(i + "");
                        row.setTimes(s[10]);
                        thread.remove(s[2]);
                        row.setFreeMemory(freeMemory);
                    } else {
                        row = new Log();
                        row.setLogName(logName);
                        row.setPodName(s[5]);
                        row.setApiName(s[8]);
                        row.setEndData(s[0] + g + s[1]);
                        row.setEndline(i + "");
                        row.setTimes(s[10]);
                        row.setThreadName(s[2]);
                        row.setFreeMemory(freeMemory);
                        re.addLast(row);

                    }
                    System.out.println(row);
                } else if (isException && row != null) {
                    row = re.getLast();
                    if (row != null) {
                        String e = row.getExceptionMsg();
                        if (e!=null&&e.length()<30000) {
                            row.setExceptionMsg(e + lt + String.format("%s (%s)", content, i));
                        } else if(content.length()<10000){
                            row.setExceptionMsg(String.format("%s (%s)", content, i));
                        }
                    }

                }
            }

        }
        System.out.println("roading end " + logFile.getName());
        return re;
    }

    public static void write(String execlPath, List<Log> data) {
        int len = data.size();
//        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(execlPath, Log.class);
        ExcelWriter excelWriterBuilder = EasyExcel.write(execlPath).build();
        WriteSheet writeSheet;
        if (len > 60000) {
            int slip = len / 60000 + 1;
            List<List<Log>> lists = ListUtil.splitAvg(data, slip);
            // 创建一个sheet

            for (int i = 0; i < slip; i++) {
                writeSheet = EasyExcel.writerSheet(i, "Sheet" + i).head(Log.class).build();
                excelWriterBuilder.write(lists.get(i), writeSheet);

//                excelWriterBuilder.sheet("Sheet" + i).doWrite(lists.get(i));
            }
        } else {
//            excelWriterBuilder.sheet("Sheet01").doWrite(data);
            writeSheet = EasyExcel.writerSheet(0, "Sheet01").head(Log.class).build();
            excelWriterBuilder.write(data, writeSheet);
        }

        excelWriterBuilder.finish();
    }

    public static void main(String[] args) {
//        testLost();
        //日志目录

        //第一个参数 分析出excel
//        EasyExcel.write(, Log.class).sheet("Sheet01").doWrite();

        write(readLogspath+"\\analysis-"+System.currentTimeMillis()+".xlsx", getInputStream(readLogspath));
    }

    @Test
    public void testLost() {
//        String row = "2023-07-15 21:00:49.571 [http-nio-9091-exec-36] INFO  [server-deploy-77f44c9b99-cc7mp/192.168.139.164] c.t.utils.logback.LogAspect - Api.slCheck 耗时: 221193";
//        String row = "2023-07-15 15:31:21.600 [http-nio-9091-exec-61] INFO  [server-deploy-7998b6dcc5-7w769/192.168.115.45] c.t.utils.logback.LogAspect - Api.menu 耗时: 20579 ";

//        String row = "2023-07-15 15:31:01.021 [http-nio-9091-exec-61] INFO  [server-deploy-7998b6dcc5-7w769/192.168.115.45] c.t.utils.logback.LogAspect - Api.menu  param:[{\"codekind\":\"1\"},null]";
//        String row = "2023-07-17 15:03:02.614 [http-nio-9091-exec-9] ERROR [server-deploy-5f48b6759-scf78/192.168.139.169] c.p.config.interceptor.RequestFilter - parameter Filter exception:{}";
        String row = "2023-07-22 00:00:58.517 [http-nio-9091-exec-9] INFO  [server-deploy-6685bf55cf-9zmwb/192.168.67.193] c.t.utils.logback.LogAspect - Api.getPicPath 耗时: 3 re:null freeMemory:1126";

        String[] s = row.split(" ");
        for (int i = 0; i < s.length; i++) {
            System.out.println(String.format("%s=%s", i, s[i]));
        }

        /**star
         *0=2023-07-15
         * 1=15:31:01.021
         * 2=[http-nio-9091-exec-61]
         * 3=INFO
         * 4=
         * 5=[server-deploy-7998b6dcc5-7w769/192.168.115.45]
         * 6=c.t.utils.logback.LogAspect
         * 7=-
         * 8=class.menu
         * 9=
         * 10=param:[{"codekind":"1"},null]
         * 11=re:null
         * 12=freeMemory:1126
         */
        /** end
         * 0=2023-07-15
         * 1=21:00:49.571
         * 2=[http-nio-9091-exec-36]
         * 3=INFO
         * 4=
         * 5=[server-deploy-77f44c9b99-cc7mp/192.168.139.164]
         * 6=c.t.utils.logback.LogAspect
         * 7=-
         * 8=Api.slCheck
         * 9=耗时:
         * 10=221193
         */
        /**
         * 0=2023-07-17
         * 1=15:03:02.614
         * 2=[http-nio-9091-exec-9]
         * 3=ERROR
         * 4=[server-deploy-5f48b6759-scf78/192.168.139.169]
         * 5=c.p.config.interceptor.RequestFilter
         * 6=-
         * 7=parameter
         * 8=Filter
         * 9=exception:{}
         */
    }

    @Test
    public void testLogTime() {
        Pattern pattern = Pattern.compile(times_reg);


        String start = "2023-07-18 08:48:31.425 [http-nio-9091-exec-8] INFO  [server-deploy-6744968b9b-4s466/192.168.138.183] c.t.utils.logback.LogAspect - Api.ocr  param:[{\"filetype\":0}]\n";
        String end = "2023-07-18 08:48:34.992 [http-nio-9091-exec-8] INFO  [server-deploy-6744968b9b-4s466/192.168.138.183] c.t.utils.logback.LogAspect - Api.ocr 耗时: 3560 re:";
        System.out.println(pattern.matcher(start).find());
        System.out.println(end.matches(times_reg));
    }
}
